package com.system.boss.monitor.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import com.system.boss.monitor.service.dto.Cpu;
import com.system.boss.monitor.service.dto.Disk;
import com.system.boss.monitor.service.dto.Ethernet;
import com.system.boss.monitor.service.dto.Memory;
import com.system.boss.monitor.service.dto.OS;
import com.system.boss.monitor.service.dto.PidstatIO;
import com.system.boss.monitor.service.dto.ProcessDetail;
import com.system.boss.monitor.service.dto.Top;
import com.system.boss.monitor.service.dto.TopTask;
import com.system.boss.monitor.service.dto.TopUsed;
import com.system.core.utils.ProcessExecutor;

import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class SystemResourceMonitor {

	public static final List<Ethernet> ethCahce = new ArrayList<Ethernet>();
	private String homedir="/";
	
	public static void main(String[] args) throws Exception {
		SystemResourceMonitor systemResourceMonitor = new SystemResourceMonitor();
		ProcessDetail top = systemResourceMonitor.getProcessDetail(3370);
		System.out.println(top);
	}
	private Pattern namePattern = Pattern.compile("(\\S*):.*flags");
	private Pattern rxBytesPattern = Pattern.compile("RX.*bytes\\s(\\S*)\\s?");
	
	private Pattern txBytesPattern = Pattern.compile("TX.*bytes\\s(\\S*)\\s?");

	@Autowired
	private Environment environment;
	
	@Autowired
	private PidstatService pidstatService;

	private String ifconfig;
	
	public List<Cpu> getCpu() {
		String cpuinfo;
		if(environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
			cpuinfo = "processor       : 0\n" +
			"vendor_id       : GenuineIntel\n" +
			"cpu family      : 6\n" +
			"model           : 85\n" +
			"model name      : Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz\n" +
			"stepping        : 7\n" +
			"microcode       : 0x1\n" +
			"cpu MHz         : 2499.996\n" +
			"cache size      : 36608 KB\n" +
			"physical id     : 0\n" +
			"siblings        : 2\n" +
			"core id         : 0\n" +
			"cpu cores       : 1\n" +
			"apicid          : 0\n" +
			"initial apicid  : 0\n" +
			"fpu             : yes\n" +
			"fpu_exception   : yes\n" +
			"cpuid level     : 22\n" +
			"wp              : yes\n" +
			"flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 arat avx512_vnni\n" +
			"bogomips        : 4999.99\n" +
			"clflush size    : 64\n" +
			"cache_alignment : 64\n" +
			"address sizes   : 46 bits physical, 48 bits virtual\n" +
			"power management:\n" +
			"\n" +
			"processor       : 1\n" +
			"vendor_id       : GenuineIntel\n" +
			"cpu family      : 6\n" +
			"model           : 85\n" +
			"model name      : Intel(R) Xeon(R) Platinum 8269CY CPU @ 2.50GHz\n" +
			"stepping        : 7\n" +
			"microcode       : 0x1\n" +
			"cpu MHz         : 2499.996\n" +
			"cache size      : 36608 KB\n" +
			"physical id     : 0\n" +
			"siblings        : 2\n" +
			"core id         : 0\n" +
			"cpu cores       : 1\n" +
			"apicid          : 1\n" +
			"initial apicid  : 1\n" +
			"fpu             : yes\n" +
			"fpu_exception   : yes\n" +
			"cpuid level     : 22\n" +
			"wp              : yes\n" +
			"flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq monitor ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 arat avx512_vnni\n" +
			"bogomips        : 4999.99\n" +
			"clflush size    : 64\n" +
			"cache_alignment : 64\n" +
			"address sizes   : 46 bits physical, 48 bits virtual\n" +
			"power management:";
		} else {
			cpuinfo = ProcessExecutor.executeOnce("cat /proc/cpuinfo",homedir)[1];
		}

		List<Cpu> cpus = new ArrayList<Cpu>();
		for(String cpustr:cpuinfo.split("\n\n")) {
			Cpu cpu = new Cpu();
			cpu.setAddressSizes(getCpuProperties("address sizes",cpustr));
			cpu.setCpuFamily(getCpuProperties("cpu family",cpustr));
			cpu.setCpuMHz(Float.parseFloat(getCpuProperties("cpu MHz",cpustr)));
			cpu.setProcessor(Integer.parseInt(getCpuProperties("processor",cpustr)));
			cpu.setFlags(getCpuProperties("flags",cpustr));
			cpu.setCacheSize(getCpuProperties("cache size",cpustr));
			cpu.setModel(getCpuProperties("model",cpustr));
			cpu.setModelName(getCpuProperties("model name",cpustr));
			cpu.setVendorId(getCpuProperties("vendor_id",cpustr));
			cpu.setFpu(getCpuProperties("fpu",cpustr));
			cpus.add(cpu);
		}
		return cpus;
	}

	public String getCpuProperties(String key,String cpustr) {
		Pattern cpuPattern = Pattern.compile(key+".*:(.*)");
		Matcher matcher = cpuPattern.matcher(cpustr);
		if(matcher.find()) {
			String tmp = matcher.group(1);
			if(StringUtils.isNotBlank(tmp)) {
				return tmp.trim();
			} else {
				return tmp;
			}
		}
		return null;
	}

	public List<Disk> getDisk() {
		String diskstr;
		if(environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
			diskstr = "文件系统                 容量  已用  可用 已用% 挂载点\n" +
			"/dev/mapper/centos-root   50G  2.6G   48G    6% /\n" +
			"devtmpfs                 1.9G     0  1.9G    0% /dev\n" +
			"tmpfs                    1.9G     0  1.9G    0% /dev/shm\n" +
			"tmpfs                    1.9G   18M  1.9G    1% /run\n" +
			"tmpfs                    1.9G     0  1.9G    0% /sys/fs/cgroup\n" +
			"/dev/sda1               1014M  145M  870M   15% /boot\n" +
			"/dev/mapper/centos-home  445G   33M  445G    1% /home\n" +
			"tmpfs                    379M     0  379M    0% /run/user/0";
		} else {
			diskstr = ProcessExecutor.executeOnce("df -h",homedir)[1];
		}
		List<Disk> disks = new ArrayList<Disk>();
		String[] diskstrs = diskstr.split("\n");
		for(int i =1; i < diskstrs.length; i++) {
			Disk disk = new Disk();
			String tmp = diskstrs[i];
			String[] items = tmp.split(" +");
			disk.setFileSystem(items[0].trim());
			disk.setBlocks(items[1].trim());
			disk.setUsed(items[2].trim());
			disk.setAvailable(items[3].trim());
			disk.setUse(items[4].trim());
			disk.setMountedOn(items[5].trim());
			disks.add(disk);
		}
		return disks;
	}

	public List<Ethernet> getEthernet() {
		String ethinfo = null;
		if(environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
			ifconfig = "ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500\n" +
					"        inet 190.168.1.37  netmask 255.255.255.0  broadcast 190.168.1.255\n" +
					"        inet6 fe80::535d:752b:f7cc:7957  prefixlen 64  scopeid 0x20<link>\n" +
					"        ether 00:0c:29:af:ce:ce  txqueuelen 1000  (Ethernet)\n" +
					"        RX packets 19322406  bytes 10251772733 (9.5 GiB)\n" +
					"        RX errors 0  dropped 221  overruns 0  frame 0\n" +
					"        TX packets 15864437  bytes 14316617274 (13.3 GiB)\n" +
					"        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0\n" +
					"\n" +
					"lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536\n" +
					"        inet 127.0.0.1  netmask 255.0.0.0\n" +
					"        inet6 ::1  prefixlen 128  scopeid 0x10<host>\n" +
					"        loop  txqueuelen 1000  (Local Loopback)\n" +
					"        RX packets 320962  bytes 909339806 (867.2 MiB)\n" +
					"        RX errors 0  dropped 0  overruns 0  frame 0\n" +
					"        TX packets 320962  bytes 909339806 (867.2 MiB)\n" +
					"        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0";
			
			ethinfo = "Settings for ens192:\n" +
					"        Supported ports: [ TP ]\n" +
					"        Supported link modes:   1000baseT/Full \n" +
					"                                10000baseT/Full \n" +
					"        Supported pause frame use: No\n" +
					"        Supports auto-negotiation: No\n" +
					"        Supported FEC modes: Not reported\n" +
					"        Advertised link modes:  Not reported\n" +
					"        Advertised pause frame use: No\n" +
					"        Advertised auto-negotiation: No\n" +
					"        Advertised FEC modes: Not reported\n" +
					"        Speed: 10000Mb/s\n" +
					"        Duplex: Full\n" +
					"        Port: Twisted Pair\n" +
					"        PHYAD: 0\n" +
					"        Transceiver: internal\n" +
					"        Auto-negotiation: off\n" +
					"        MDI-X: Unknown\n" +
					"        Supports Wake-on: uag\n" +
					"        Wake-on: d\n" +
					"        Link detected: yes";
			
		} else {
			ifconfig = ProcessExecutor.executeOnce("ifconfig -a",homedir)[1];
		}
		List<Ethernet> ethernets = new ArrayList<Ethernet>();
		for (String name : getName()) {
			ethernets.add(Ethernet.builder().name(name).build());
		}

		List<String> tmpList = getEthernetProperties("inet");
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setInet(tmpList.get(i));
		}
		tmpList = getEthernetProperties("netmask");
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setNetmask(tmpList.get(i));
		}
		tmpList = getEthernetProperties("inet6");
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setInet6(tmpList.get(i));
		}
		tmpList = getEthernetProperties("mtu");
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setMtu(Integer.parseInt(tmpList.get(i)));
		}
		tmpList = getEthernetProperties("broadcast");
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setBroadcast(tmpList.get(i));
		}
		tmpList = getEthernetProperties("RX packets");
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setRxpackets(Long.parseLong(tmpList.get(i)));
		}
		tmpList = getEthernetProperties("TX packets");
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setTxpackets(Long.parseLong(tmpList.get(i)));
		}
		tmpList = getRxBytes();
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setRxbytes(Long.parseLong(tmpList.get(i)));
		}
		tmpList = getTxBytes();
		for (int i = 0; i < tmpList.size(); i++) {
			ethernets.get(i).setTxbytes(Long.parseLong(tmpList.get(i)));
		}
		
		
		
		for(Ethernet ethernet : ethernets) {
			ethernet.setUpSpeed((int)Math.ceil(100f/8));
			ethernet.setDownSpeed((int)Math.ceil(10f/8));
			if(!ethernet.getName().equalsIgnoreCase("lo") && !environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
				ethinfo = ProcessExecutor.executeOnce("ethtool "+ ethernet.getName(),homedir)[1];
			}
			if(ethinfo != null) {
				String tmpSpeed = getEthernetDetail("Speed", ethinfo);
				if(tmpSpeed == null) {
					tmpSpeed = "Unknown";
				}
				if(tmpSpeed.contains("Unknown")) {
					tmpSpeed = "0 Mb/s";
				}
				ethernet.setSpeed(tmpSpeed);
				if(ethernet.getUpSpeed() == null && StringUtils.isNotBlank(ethernet.getSpeed())) {
					ethernet.setUpSpeed(Integer.parseInt(StringUtils.remove(ethernet.getSpeed(), "Mb/s").trim()));
				}
				if(ethernet.getDownSpeed() == null && StringUtils.isNotBlank(ethernet.getSpeed())) {
					ethernet.setDownSpeed(Integer.parseInt(StringUtils.remove(ethernet.getSpeed(), "Mb/s").trim()));
				}
				ethernet.setSupportedPorts(getEthernetDetail("Supported ports", ethinfo));
				ethernet.setPort(getEthernetDetail("Port", ethinfo));
				ethernet.setDuplex(getEthernetDetail("Duplex", ethinfo));
				ethernet.setPhyad(getEthernetDetail("PHYAD", ethinfo));
			}
			if(!environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
				ethinfo = null;
			}
		}

		return ethernets;
	}

	private String getEthernetDetail(String key, String str) {
		Pattern namePattern = Pattern.compile(key+".*:(.*)");
		Matcher matcher = namePattern.matcher(str);
		if(matcher.find()) {
			String tmp = matcher.group(1);
			if(StringUtils.isNotBlank(tmp)) {
				return tmp.trim();
			} else {
				return tmp;
			}
		}
		return null;
	}
	
	private List<String> getEthernetProperties(String key) {
		Pattern propertyPattern = Pattern.compile("\\s*" + key + "\\s{1,}(\\S*)\\s?");
		Matcher matcher = propertyPattern.matcher(ifconfig);
		ArrayList<String> names = new ArrayList<String>();
		while (matcher.find()) {
			names.add(matcher.group(1));
		}
		return names;
	}
	
	public Memory getMemory() {
		String men;
		if(environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
			men = "MemTotal:        3880432 kB\n" +
			"MemFree:         1128496 kB\n" +
			"MemAvailable:    1489744 kB\n" +
			"Buffers:               0 kB\n" +
			"Cached:           547172 kB\n" +
			"SwapCached:          688 kB\n" +
			"Active:          1729536 kB\n" +
			"Inactive:         679336 kB\n" +
			"Active(anon):    1407644 kB\n" +
			"Inactive(anon):   496084 kB\n" +
			"Active(file):     321892 kB\n" +
			"Inactive(file):   183252 kB\n" +
			"Unevictable:           0 kB\n" +
			"Mlocked:               0 kB\n" +
			"SwapTotal:       4063228 kB\n" +
			"SwapFree:        4060924 kB\n" +
			"Dirty:                56 kB\n" +
			"Writeback:             0 kB\n" +
			"AnonPages:       1861104 kB\n" +
			"Mapped:            69176 kB\n" +
			"Shmem:             42028 kB\n" +
			"Slab:             210828 kB\n" +
			"SReclaimable:     121560 kB\n" +
			"SUnreclaim:        89268 kB\n" +
			"KernelStack:        7168 kB\n" +
			"PageTables:        13484 kB\n" +
			"NFS_Unstable:          0 kB\n" +
			"Bounce:                0 kB\n" +
			"WritebackTmp:          0 kB\n" +
			"CommitLimit:     6003444 kB\n" +
			"Committed_AS:    3170264 kB\n" +
			"VmallocTotal:   34359738367 kB\n" +
			"VmallocUsed:      152452 kB\n" +
			"VmallocChunk:   34359341052 kB\n" +
			"HardwareCorrupted:     0 kB\n" +
			"AnonHugePages:      6144 kB\n" +
			"CmaTotal:              0 kB\n" +
			"CmaFree:               0 kB\n" +
			"HugePages_Total:       0\n" +
			"HugePages_Free:        0\n" +
			"HugePages_Rsvd:        0\n" +
			"HugePages_Surp:        0\n" +
			"Hugepagesize:       2048 kB\n" +
			"DirectMap4k:      120704 kB\n" +
			"DirectMap2M:     4073472 kB\n" +
			"DirectMap1G:     2097152 kB";
		} else {
			men = ProcessExecutor.executeOnce("cat /proc/meminfo",homedir)[1];
		}
		Memory memory = new Memory();
		memory.setMemTotal(getMemProperties("MemTotal",men));
		memory.setMemFree(getMemProperties("MemFree",men));
		memory.setSwapFree(getMemProperties("SwapFree",men));
		memory.setSwapTotal(getMemProperties("SwapTotal",men));
		return memory;
	}
	
	public Integer getMemProperties(String key,String memstr) {
		Pattern cpuPattern = Pattern.compile(key+".*:(.*)kB");
		Matcher matcher = cpuPattern.matcher(memstr);
		if(matcher.find()) {
			String tmp = matcher.group(1);
			if(StringUtils.isNotBlank(tmp)) {
				return Integer.parseInt(tmp.trim());
			} else {
				return null;
			}
		}
		return null;
	}
	
	private List<String> getName() {
		Matcher matcher = namePattern.matcher(ifconfig);
		ArrayList<String> names = new ArrayList<String>();
		while (matcher.find()) {
			names.add(matcher.group(1));
		}
		return names;
	}
	
	public OS getOS() {
		String osstr;
		String readHat;
		if(environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
			osstr = "Linux version 3.10.0-957.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) #1 SMP Thu Nov 8 23:39:32 UTC 2018";
			if(osstr.contains("Red Hat")) {
				readHat = "CentOS Linux release 7.6.1810 (Core) ";
			} else {
				readHat = "";
			}
		} else {
			osstr = ProcessExecutor.executeOnce("cat /proc/version",homedir)[1];
			if(osstr.contains("Red Hat")) {
				readHat = ProcessExecutor.executeOnce("cat /etc/redhat-release",homedir)[1];
			} else {
				readHat = "";
			}
		}
		OS os = new OS();
		os.setOs(osstr);
		os.setRedHat(readHat);
		return os;
	}
	
	public ProcessDetail getProcessDetail(Integer pid) {
		String processStr;
		if(environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
			processStr = "root      "+pid+"  4.8 15.7 4926680 609832 pts/0  Sl   10:21   2:59 java -jar -server -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:+PrintAdaptiveSizePolicy -XX:+UseFastAccessorMethods -XX:+TieredCompilation -XX:+ExplicitGCInvokesConcurrent -Dfile.encoding=utf-8 -Dspring.profiles.active=test paycore-assemble/target/paycore-1.0.jar";
		} else {
			processStr = ProcessExecutor.executeOnce("ps u "+pid+"|grep -v 'USER'",homedir)[1];
		}
		String[] tmp = processStr.split("\\s+");
		ProcessDetail processDetail = new ProcessDetail();
		try {
			processDetail.setUser(tmp[0]);
			processDetail.setPid(Integer.parseInt(tmp[1]));
			processDetail.setCpu(Float.parseFloat(tmp[2]));
			processDetail.setMem(Float.parseFloat(tmp[3]));
			processDetail.setVsz(Integer.parseInt(tmp[4]));
			processDetail.setRss(Integer.parseInt(tmp[5]));
			processDetail.setTty(tmp[6]);
			processDetail.setStat(tmp[7]);
			processDetail.setStart(tmp[8]);
			processDetail.setTime(tmp[9]);
		} catch (Exception e) {
			log.error("进程信息解析错误，解析元数据是：{}",processStr);
			return processDetail;
		}
		
		StringBuilder cmd = new StringBuilder();
		for(int i = 10; i<tmp.length; i++) {
			cmd.append(tmp[i]);
			cmd.append(" ");
		}
		processDetail.setCommand(cmd.toString().trim());
		return processDetail;
	}
	
	public List<String> getRxBytes() {
		Matcher matcher = rxBytesPattern.matcher(ifconfig);
		ArrayList<String> names = new ArrayList<String>();

		while (matcher.find()) {
			names.add(matcher.group(1));
		}
		return names;
	}
	
	public Top getTop() throws IOException {
		String topstr;
		if(environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
//		if(true) {
			topstr = "top - 09:29:58 up 6 days, 23:59,  1 user,  load average: 0.00, 0.04, 0.06\n" +
					"Tasks: 101 total,   1 running, 100 sleeping,   0 stopped,   0 zombie\n" +
					"%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st\n" +
					"KiB Mem :  7733060 total,  5078844 free,  1495964 used,  1158252 buff/cache\n" +
					"KiB Swap:        0 total,        0 free,        0 used.  5991340 avail Mem \n" +
					"\n" +
					"  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND\n" +
					" 3139 tomcat    20   0 5944324   1.3g  15188 S   0.0 17.2   1:06.24 java\n" +
					" 1117 root      20   0  574196  17416   6120 S   0.0  0.2   0:38.74 tuned\n" +
					" 9030 root      10 -10  125576  13888   9552 S   0.0  0.2  51:25.36 AliYunDun\n" +
					"  507 root      20   0   47272  12580  12264 S   0.0  0.2   0:01.36 systemd-journal\n" +
					"  614 polkitd   20   0  612352  10240   4788 S   0.0  0.1   0:01.08 polkitd\n" +
					" 1190 root      20   0  226740   8072   7192 S   0.0  0.1   0:11.56 rsyslogd\n" +
					" 2703 root      20   0  157320   5928   4568 S   0.0  0.1   0:00.03 sshd\n" +
					" 2926 root      20   0  157476   5924   4564 S   0.0  0.1   0:01.33 sshd\n" +
					"11321 root      20   0  578056   4520   2820 S   0.0  0.1   0:18.36 automount\n" +
					" 1201 root      20   0  112920   4324   3304 S   0.0  0.1   0:00.01 sshd\n" +
					" 8983 root      10 -10   32524   4040   2568 S   0.0  0.1   1:17.44 AliYunDunUpdate\n" +
					"    1 root      20   0   43560   3888   2600 S   0.0  0.1   0:03.80 systemd\n" +
					" 1191 root      20   0   32604   3280   2596 S   0.0  0.0   8:44.67 aliyun-service\n" +
					" 2930 root      20   0   72248   2872   2112 S   0.0  0.0   0:00.00 sftp-server\n" +
					" 2948 root      20   0   72248   2684   1952 S   0.0  0.0   0:00.22 sftp-server\n" +
					"  620 dbus      20   0   58144   2364   1824 S   0.0  0.0   0:02.55 dbus-daemon\n" +
					" 1062 root      20   0  102896   2360    308 S   0.0  0.0   0:00.00 dhclient\n" +
					" 2709 root      20   0  115448   2120   1676 S   0.0  0.0   0:00.00 bash\n" +
					" 4582 root      20   0  161888   2080   1520 R   0.0  0.0   0:00.00 top\n" +
					"  542 root      20   0   44876   2008   1324 S   0.0  0.0   0:00.09 systemd-udevd\n" +
					"  630 chrony    20   0  117804   1868   1356 S   0.0  0.0   0:01.14 chronyd\n" +
					" 1203 rpcuser   20   0   42436   1752    916 S   0.0  0.0   0:00.01 rpc.statd\n" +
					"  619 root      20   0   26380   1748   1452 S   0.0  0.0   0:01.37 systemd-logind\n" +
					" 1206 root      20   0  126292   1600    980 S   0.0  0.0   0:00.60 crond\n" +
					"  784 rpc       20   0   69276   1384    820 S   0.0  0.0   0:00.40 rpcbind\n" +
					"  788 root      20   0  195104   1236    768 S   0.0  0.0   0:00.00 gssproxy\n" +
					" 1204 root      20   0   25908    936    736 S   0.0  0.0   0:00.00 atd\n" +
					"  562 root      16  -4   55528    892    484 S   0.0  0.0   0:00.33 auditd\n" +
					" 1210 root      20   0  110108    864    732 S   0.0  0.0   0:00.00 agetty\n" +
					" 1209 root      20   0  110108    852    724 S   0.0  0.0   0:00.00 agetty\n" +
					"    2 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kthreadd\n" +
					"    4 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H\n" +
					"    6 root      20   0       0      0      0 S   0.0  0.0   0:00.49 ksoftirqd/0\n" +
					"    7 root      rt   0       0      0      0 S   0.0  0.0   0:00.17 migration/0\n" +
					"    8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh\n" +
					"    9 root      20   0       0      0      0 S   0.0  0.0   0:29.60 rcu_sched\n" +
					"   10 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 lru-add-drain\n" +
					"   11 root      rt   0       0      0      0 S   0.0  0.0   0:00.73 watchdog/0\n" +
					"   12 root      rt   0       0      0      0 S   0.0  0.0   0:00.39 watchdog/1\n" +
					"   13 root      rt   0       0      0      0 S   0.0  0.0   0:01.91 migration/1\n" +
					"   14 root      20   0       0      0      0 S   0.0  0.0   0:00.26 ksoftirqd/1\n" +
					"   15 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kworker/1:0\n" +
					"   16 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/1:0H\n" +
					"   17 root      rt   0       0      0      0 S   0.0  0.0   0:00.64 watchdog/2\n" +
					"   18 root      rt   0       0      0      0 S   0.0  0.0   0:00.20 migration/2\n" +
					"   19 root      20   0       0      0      0 S   0.0  0.0   0:00.51 ksoftirqd/2\n" +
					"   20 root      20   0       0      0      0 S   0.0  0.0   0:07.16 kworker/2:0\n" +
					"   21 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/2:0H\n" +
					"   22 root      rt   0       0      0      0 S   0.0  0.0   0:00.40 watchdog/3\n" +
					"   23 root      rt   0       0      0      0 S   0.0  0.0   0:01.90 migration/3\n" +
					"   24 root      20   0       0      0      0 S   0.0  0.0   0:00.25 ksoftirqd/3\n" +
					"   26 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/3:0H\n" +
					"   28 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kdevtmpfs\n" +
					"   29 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 netns\n" +
					"   30 root      20   0       0      0      0 S   0.0  0.0   0:00.60 khungtaskd\n" +
					"   31 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 writeback\n" +
					"   32 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kintegrityd\n" +
					"   33 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 bioset\n" +
					"   34 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 bioset\n" +
					"   35 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 bioset\n" +
					"   36 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kblockd\n" +
					"   37 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 md\n" +
					"   38 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 edac-poller\n" +
					"   39 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 watchdogd\n" +
					"   40 root      20   0       0      0      0 S   0.0  0.0   0:07.02 kworker/0:1\n" +
					"   46 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kswapd0\n" +
					"   47 root      25   5       0      0      0 S   0.0  0.0   0:00.00 ksmd\n" +
					"   48 root      39  19       0      0      0 S   0.0  0.0   0:02.08 khugepaged\n" +
					"   49 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 crypto\n" +
					"   57 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kthrotld\n" +
					"   59 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kmpath_rdacd\n" +
					"   60 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kaluad\n" +
					"   61 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kpsmoused\n" +
					"   62 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 ipv6_addrconf\n" +
					"   75 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 deferwq\n" +
					"   76 root      20   0       0      0      0 S   0.0  0.0   0:02.66 kworker/3:1\n" +
					"  110 root      20   0       0      0      0 S   0.0  0.0   0:00.05 kauditd\n" +
					"  114 root      20   0       0      0      0 S   0.0  0.0   0:02.49 kworker/1:2\n" +
					"  251 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 ata_sff\n" +
					"  252 root      20   0       0      0      0 S   0.0  0.0   0:00.00 scsi_eh_0\n" +
					"  253 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 scsi_tmf_0\n" +
					"  254 root      20   0       0      0      0 S   0.0  0.0   0:00.00 scsi_eh_1\n" +
					"  255 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 scsi_tmf_1\n" +
					"  313 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 ttm_swap\n" +
					"  397 root       0 -20       0      0      0 S   0.0  0.0   0:01.85 kworker/2:1H\n" +
					"  401 root       0 -20       0      0      0 S   0.0  0.0   0:00.08 kworker/0:1H\n" +
					"  409 root      20   0       0      0      0 S   0.0  0.0   0:02.32 jbd2/vda1-8\n" +
					"  410 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 ext4-rsv-conver\n" +
					"  473 root       0 -20       0      0      0 S   0.0  0.0   0:00.49 kworker/3:1H\n" +
					"  482 root       0 -20       0      0      0 S   0.0  0.0   0:00.03 kworker/1:1H\n" +
					"  519 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kworker/3:2\n" +
					"  566 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 rpciod\n" +
					"  567 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 xprtiod\n" +
					"  833 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 nfit\n" +
					" 1399 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 nfsiod\n" +
					" 3992 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kworker/u8:1\n" +
					"19510 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0\n" +
					"20036 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kworker/2:1\n" +
					"22228 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kworker/u8:2\n" +
					"27794 root      20   0       0      0      0 S   0.0  0.0   0:00.05 kworker/u8:0\n" +
					"30760 root      20   0       0      0      0 S   0.0  0.0   0:00.00 nfsv4.1-svc";
		} else {
			topstr = ProcessExecutor.executeOnce("top -b -o RES -n 1",homedir)[1];
		}
		StringReader stringReader = new StringReader(topstr);
		BufferedReader br = new BufferedReader(stringReader);
		String tmp = null;
		int line = 1;
		Top top = new Top();
		ArrayList<TopTask> topTasks = new ArrayList<TopTask>();
		while((tmp = br.readLine()) != null) {
			
			if(line == 2) {
				top.setTasksTotal(TopPattern.getInteger("total", tmp));
				top.setTasksRunning(TopPattern.getInteger("running", tmp));
				top.setTasksSleeping(TopPattern.getInteger("sleeping", tmp));
				top.setTasksStopped(TopPattern.getInteger("stopped", tmp));
				top.setTasksZombie(TopPattern.getInteger("zombie", tmp));
			}
			
			if(line == 3) {
				top.setCpuUser(TopPattern.getFloat("us", tmp));
				top.setCpuSystem(TopPattern.getFloat("sy", tmp));
				top.setCpuNice(TopPattern.getFloat("ni", tmp));
				top.setCpuIdle(TopPattern.getFloat("id", tmp));
				top.setCpuIOWait(TopPattern.getFloat("wa", tmp));
				top.setCpuIOWait(TopPattern.getFloat("wa", tmp));
				top.setCpuHardwareIRQ(TopPattern.getFloat("hi", tmp));
				top.setCpuSoftwareIRQ(TopPattern.getFloat("si", tmp));
				top.setCpuStealTime(TopPattern.getFloat("st", tmp));
			}
			
			if(line == 4) {
				top.setMemTotal(TopPattern.getLong("total", tmp));
				top.setMemFree(TopPattern.getLong("free", tmp));
				top.setMemUsed(TopPattern.getLong("used", tmp));
				top.setMemBuffCache(TopPattern.getLong("buff/cache", tmp));
			}
			
			if(line == 5) {
				top.setSwapTotal(TopPattern.getLong("total", tmp));
				top.setSwapFree(TopPattern.getLong("free", tmp));
				top.setSwapUsed(TopPattern.getLong("used", tmp));
				top.setSwapAvailMem(TopPattern.getLong("avail Mem", tmp));
			}
			
			if(line > 5) {
				if(tmp != null && StringUtils.isNotBlank(tmp.trim())) {
					String[] pstr = tmp.trim().split("\\s+");
					if(!StringUtils.isNumeric(pstr[0])) {
						continue;
					}
					TopTask topTask = new TopTask();
					topTask.setPid(Long.parseLong(pstr[0]));
					topTask.setUser(pstr[1]);
					topTask.setPr(pstr[2]);
					topTask.setNi(Integer.parseInt(pstr[3]));
					
					topTask.setVirt(pstr[4]);
					topTask.setRes(pstr[5]);
					topTask.setShr(pstr[6]);
					
					topTask.setS(pstr[7]);
					topTask.setCpu(Float.parseFloat(pstr[8]));
					topTask.setMem(Float.parseFloat(pstr[9]));
					topTask.setTime(pstr[10]);
					topTask.setCommand(pstr[11]);
					
					topTasks.add(topTask);
				}
			}
			
			line ++;
		}
		List<PidstatIO> io = pidstatService.reportIO();
		for(TopTask toptask:topTasks) {
			for(PidstatIO pidstatIO:io) {
				if(toptask.getPid().longValue() == pidstatIO.getPid().longValue()) {
					toptask.setWrite(pidstatIO.getWrite().floatValue());
					toptask.setRead(pidstatIO.getRead().floatValue());
					continue;
				}
			}
		}
		top.setTopTask(topTasks);
		return top;
	}
	
	public TopUsed getTopUsed() {
		TopUsed topUsed = new TopUsed();
		if(environment.getActiveProfiles()[0].equalsIgnoreCase("dev")) {
			topUsed.setCpuUsed(2.3f);
			topUsed.setMemUsed(63.22f);
			topUsed.setSwapUsed(99.9f);
		} else {
			String cpu = ProcessExecutor.executeOnce("top -b -n 1 | grep 'Cpu(s)'|awk '{print $2+$4}'",homedir)[1];
			String mem = ProcessExecutor.executeOnce("top -b -n 1 | grep 'KiB Mem'|awk '{print $8/$4*100}'",homedir)[1];
			if(StringUtils.isBlank(mem)) {
				mem = ProcessExecutor.executeOnce("top -b -E k -n 1 | grep 'KiB Mem'|awk '{print $8/$4*100}'",homedir)[1];
			}
			String swap = ProcessExecutor.executeOnce("top -b -n 1 | grep 'KiB Swap'|awk '{if($3>0) print ($7/$3)*100;else print 0}'",homedir)[1];
			if(StringUtils.isBlank(swap)) {
				swap = ProcessExecutor.executeOnce("top -b -E k -n 1 | grep 'KiB Swap'|awk '{if($3>0) print ($7/$3)*100;else print 0}'",homedir)[1];
			}
			try {
				topUsed.setCpuUsed(Float.parseFloat(cpu));
				topUsed.setMemUsed(Float.parseFloat(mem));
				topUsed.setSwapUsed(Float.parseFloat(swap));
			} catch (Exception e) {
				topUsed.setCpuUsed(0f);
				topUsed.setMemUsed(0f);
				topUsed.setSwapUsed(0f);
				log.error("",e);
			}
		}
		return topUsed;
	}

	public List<String> getTxBytes() {
		Matcher matcher = txBytesPattern.matcher(ifconfig);
		ArrayList<String> names = new ArrayList<String>();

		while (matcher.find()) {
			names.add(matcher.group(1));
		}
		return names;
	}

	//@Scheduled(cron = "0/1 * * * * ?")
	public void monitor() {
		try {
			List<Ethernet> ethernets = getEthernet();
			if (ethCahce.size() > 0) {
				for (Ethernet ethernet : ethCahce) {
					for (Ethernet now : ethernets) {
						if (ethernet.equals(now)) {
							now.setUpPeerSecond(now.getTxbytes() - ethernet.getTxbytes());
							now.setDownPeerSecond(now.getRxbytes() - ethernet.getRxbytes());
							now.setCostTime((int)(now.getTimestamp() - ethernet.getTimestamp()));
						}
					}
				}
				ethCahce.clear();
			}
			ethCahce.addAll(ethernets);
		} catch (Exception e) {
			log.error("",e);
		}
	}
}
